package com.tianhai.db;

import java.io.File;
import java.util.List;

/**
 * WAL测试类
 */
public class WALTest {
    
    public static void main(String[] args) {
        System.out.println("========================================");
        System.out.println("         WAL预写日志测试");
        System.out.println("========================================\n");
        
        String walFilePath = "test.wal";
        int totalTests = 0;
        int passedTests = 0;
        
        // 清理旧文件
        new File(walFilePath).delete();
        
        // 测试1: 记录事务日志
        System.out.println("【测试1】记录事务日志");
        try {
            WAL wal = new WAL(walFilePath);
            
            // 事务1: INSERT操作
            wal.logTransaction(1, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(1, WAL.LogType.INSERT, "users", "{id:1, name:'张三', age:25}");
            wal.logTransaction(1, WAL.LogType.INSERT, "users", "{id:2, name:'李四', age:30}");
            wal.logTransaction(1, WAL.LogType.COMMIT, null, null);
            
            // 事务2: UPDATE操作（未提交）
            wal.logTransaction(2, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(2, WAL.LogType.UPDATE, "users", "{id:1, age:26}");
            
            wal.close();
            
            System.out.println("✓ 成功记录4条日志（事务1已提交，事务2未提交）");
            passedTests++;
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试2: 恢复已提交事务
        System.out.println("【测试2】恢复已提交事务");
        try {
            WAL wal = new WAL(walFilePath);
            List<WAL.Transaction> transactions = wal.recover();
            
            if (transactions.size() == 1) {
                WAL.Transaction txn = transactions.get(0);
                System.out.println("✓ 恢复成功");
                System.out.println("  事务ID: " + txn.txnId);
                System.out.println("  状态: " + txn.status);
                System.out.println("  日志数: " + txn.logRecords.size());
                System.out.println("  日志内容:");
                for (WAL.LogRecord record : txn.logRecords) {
                    System.out.println("    " + record);
                }
                
                if (txn.txnId == 1 && txn.status == WAL.TransactionStatus.COMMITTED && 
                    txn.logRecords.size() == 4) {
                    passedTests++;
                }
            } else {
                System.out.println("✗ 恢复的事务数量不正确: " + transactions.size());
            }
            
            wal.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试3: 多个已提交事务
        System.out.println("【测试3】多个已提交事务");
        try {
            new File(walFilePath).delete();
            WAL wal = new WAL(walFilePath);
            
            // 事务1
            wal.logTransaction(1, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(1, WAL.LogType.INSERT, "users", "{id:1}");
            wal.logTransaction(1, WAL.LogType.COMMIT, null, null);
            
            // 事务2
            wal.logTransaction(2, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(2, WAL.LogType.UPDATE, "users", "{id:1, age:30}");
            wal.logTransaction(2, WAL.LogType.COMMIT, null, null);
            
            // 事务3（未提交）
            wal.logTransaction(3, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(3, WAL.LogType.DELETE, "users", "{id:1}");
            
            wal.close();
            
            // 恢复
            wal = new WAL(walFilePath);
            List<WAL.Transaction> transactions = wal.recover();
            
            if (transactions.size() == 2) {
                System.out.println("✓ 成功恢复2个已提交事务");
                for (WAL.Transaction txn : transactions) {
                    System.out.println("  " + txn);
                }
                passedTests++;
            } else {
                System.out.println("✗ 恢复的事务数量不正确: " + transactions.size());
            }
            
            wal.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试4: ABORT事务不恢复
        System.out.println("【测试4】ABORT事务不恢复");
        try {
            new File(walFilePath).delete();
            WAL wal = new WAL(walFilePath);
            
            // 事务1 - 提交
            wal.logTransaction(1, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(1, WAL.LogType.INSERT, "users", "{id:1}");
            wal.logTransaction(1, WAL.LogType.COMMIT, null, null);
            
            // 事务2 - 中止
            wal.logTransaction(2, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(2, WAL.LogType.INSERT, "users", "{id:2}");
            wal.logTransaction(2, WAL.LogType.ABORT, null, null);
            
            wal.close();
            
            // 恢复
            wal = new WAL(walFilePath);
            List<WAL.Transaction> transactions = wal.recover();
            
            if (transactions.size() == 1 && transactions.get(0).txnId == 1) {
                System.out.println("✓ 正确处理：只恢复已提交事务，忽略ABORT事务");
                passedTests++;
            } else {
                System.out.println("✗ ABORT事务处理不正确");
            }
            
            wal.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试5: 空WAL恢复
        System.out.println("【测试5】空WAL恢复");
        try {
            new File(walFilePath).delete();
            WAL wal = new WAL(walFilePath);
            
            List<WAL.Transaction> transactions = wal.recover();
            
            if (transactions.isEmpty()) {
                System.out.println("✓ 空WAL正确返回空列表");
                passedTests++;
            } else {
                System.out.println("✗ 空WAL恢复异常");
            }
            
            wal.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 测试6: Truncate清空日志
        System.out.println("【测试6】Truncate清空日志");
        try {
            WAL wal = new WAL(walFilePath);
            
            // 记录日志
            wal.logTransaction(1, WAL.LogType.BEGIN, null, null);
            wal.logTransaction(1, WAL.LogType.INSERT, "users", "{id:1}");
            wal.logTransaction(1, WAL.LogType.COMMIT, null, null);
            
            // 清空
            wal.truncate();
            
            // 恢复
            List<WAL.Transaction> transactions = wal.recover();
            
            if (transactions.isEmpty()) {
                System.out.println("✓ Truncate成功清空日志");
                passedTests++;
            } else {
                System.out.println("✗ Truncate未清空日志");
            }
            
            wal.close();
        } catch (Exception e) {
            System.out.println("✗ 异常: " + e.getMessage());
            e.printStackTrace();
        }
        totalTests++;
        System.out.println();
        
        // 清理测试文件
        new File(walFilePath).delete();
        
        // 测试结果
        System.out.println("========================================");
        System.out.println("           测试结果汇总");
        System.out.println("========================================");
        System.out.println("总测试数: " + totalTests);
        System.out.println("通过数: " + passedTests);
        System.out.println("失败数: " + (totalTests - passedTests));
        System.out.println("通过率: " + String.format("%.1f%%", passedTests * 100.0 / totalTests));
        System.out.println("----------------------------------------");
        
        if (passedTests == totalTests) {
            System.out.println("✓✓✓ 所有测试通过！");
        } else {
            System.out.println("✗✗✗ 部分测试失败");
        }
        System.out.println("========================================\n");
    }
}
